//
//  ST_QuickMessageVoiceViewController.swift
//  btvideo
//
//  快捷搭讪语音录制
//
//  Created by mac on 2021/9/6.
//  Copyright © 2021 JarvanZhang. All rights reserved.
//

import UIKit
import RxSwift

class ST_QuickMessageVoiceViewController: UIViewController {
    
    enum State {
        case ready
        case recording
        case check
    }

    /// 点击关闭弹窗手势
    lazy var dismiss_tap: UITapGestureRecognizer = {
        let tap = UITapGestureRecognizer()
        tap.delegate = self
        return tap
    }()
    
    /// 卡片背景
    let bgView: UIView = {
        let view = UIView()
        view.backgroundColor = .white
        return view
    }()
    
    /// 标题
    private lazy var titleLabel: UILabel = {
        let label = UILabel()
        label.text = viewModel.config.title
        label.textAlignment = .center
        label.textColor = UIColor(hexString: "#333333")
        label.font = .systemFont(ofSize: 18, weight: .medium)
        return label
    }()
    
    /// 介绍文字第一行
    private lazy var intro_label: UILabel = {
        let label = UILabel()
        label.text = viewModel.config.message
        label.textColor = UIColor(hexString: "#565656")
        label.font = .systemFont(ofSize: 15, weight: .regular)
        return label
    }()
    
    /// 介绍文字第二行
    private lazy var subintro_label: UILabel = {
        let label = UILabel()
        label.text = viewModel.config.msgDesc
        label.textColor = UIColor(hexString: "#ACB4C0")
        label.font = .systemFont(ofSize: 13, weight: .medium)
        return label
    }()
    
    /// 时长
    let duration_label: UILabel = {
        let label = UILabel()
        label.text = "0s"
        label.textColor = UIColor(hexString: "#333333")
        label.font = .systemFont(ofSize: 18, weight: .medium)
        return label
    }()
    
    /// 重录按钮
    let re_button: ST_VerticalButton = {
        let button = ST_VerticalButton()
        button.setImageForAllStates(#imageLiteral(resourceName: "quickMessage_icon_re"))
        button.setTitleForAllStates(NSAttributedString(string: "重新录制", attributes: [.foregroundColor: UIColor(hexString: "#ACB4C0")!, .font: UIFont.systemFont(ofSize: 13)]))
        button.title_bottom_offset = 10
        return button
    }()
    
    /// 录音按钮
    let record_button: ST_VerticalButton = {
        let button = ST_VerticalButton()
        button.setImageForAllStates(#imageLiteral(resourceName: "quickMessage_icon_recorder"))
        button.setTitleForAllStates(NSAttributedString(string: "点击录制", attributes: [.foregroundColor: UIColor(hexString: "#ACB4C0")!, .font: UIFont.systemFont(ofSize: 13)]))
        button.title_bottom_offset = 10
        return button
    }()
    
    /// 停止录音按钮
    let stop_record_button: ST_VerticalButton = {
        let button = ST_VerticalButton()
        button.setImageForAllStates(#imageLiteral(resourceName: "quickMessage_icon_stopRecord"))
        button.setTitleForAllStates(NSAttributedString(string: "点击结束", attributes: [.foregroundColor: UIColor(hexString: "#ACB4C0")!, .font: UIFont.systemFont(ofSize: 13)]))
        button.title_bottom_offset = 10
        return button
    }()
    
    /// 播放按钮
    let play_button: ST_VerticalButton = {
        let button = ST_VerticalButton()
        button.setImageForAllStates(#imageLiteral(resourceName: "quickMessage_icon_play3"))
        button.setTitleForAllStates(NSAttributedString(string: "点击播放", attributes: [.foregroundColor: UIColor(hexString: "#ACB4C0")!, .font: UIFont.systemFont(ofSize: 13)]))
        button.title_bottom_offset = 10
        button.imageView.animationImages = [#imageLiteral(resourceName: "quickMessage_icon_play1"), #imageLiteral(resourceName: "quickMessage_icon_play2"), #imageLiteral(resourceName: "quickMessage_icon_play3")]
        button.imageView.animationDuration = 2
        button.imageView.animationRepeatCount = 0
        return button
    }()
    
    /// 保存按钮
    let save_button: ST_VerticalButton = {
        let button = ST_VerticalButton()
        button.setImageForAllStates(#imageLiteral(resourceName: "quickMessage_icon_save"))
        button.setTitleForAllStates(NSAttributedString(string: "保存", attributes: [.foregroundColor: UIColor(hexString: "#ACB4C0")!, .font: UIFont.systemFont(ofSize: 13)]))
        button.title_bottom_offset = 10
        return button
    }()
    
    /// 操作按钮布局
    lazy var operation_stack_view: UIStackView = {
        let stackView = UIStackView()
        stackView.axis = .horizontal
        stackView.alignment = .center
        stackView.spacing = 30
        stackView.addArrangedSubviews([re_button, record_button, stop_record_button, play_button, save_button])
        return stackView
    }()
    
    /// 录音控制器
    let recorder_controller = ST_RecorderController()
    
    /// 时间格式化
    let date_components_formatter: DateComponentsFormatter = {
        let formatter = DateComponentsFormatter()
        formatter.allowedUnits = [.second]
        formatter.unitsStyle = .positional
//        formatter.zeroFormattingBehavior = .pad
        return formatter
    }()
    
    var disposeBag = DisposeBag()
    let viewModel:ST_QuickMessageVoiceViewModel
    var onAdd: (() -> Void)? = nil
    
    init(viewModel:ST_QuickMessageVoiceViewModel){
        
        self.viewModel = viewModel
        super.init(nibName: nil, bundle: nil)
        overCurrentContext = true
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()

        setup_views()
        bindRx()
    }
    
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        
        bgView.roundCorners([.topLeft, .topRight], radius: 16)
    }
    
    @available(iOS 11.0, *)
    override func viewSafeAreaInsetsDidChange() {
        super.viewSafeAreaInsetsDidChange()
        
        bgView.snp.updateConstraints { make in
            make.height.equalTo(375 + view.safeAreaInsets.bottom)
        }
    }

    func setup_views() {
        
        view.addGestureRecognizer(dismiss_tap)
        
        view.addSubview(bgView)
        bgView.snp.makeConstraints { make in
            make.leading.bottom.trailing.equalToSuperview()
            make.height.equalTo(375)
        }
        
        bgView.addSubview(titleLabel)
        titleLabel.snp.makeConstraints { make in
            make.top.leading.trailing.equalToSuperview()
            make.height.equalTo(65)
        }
        
        bgView.addSubview(intro_label)
        intro_label.snp.makeConstraints { make in
            make.top.equalTo(titleLabel.snp.bottom)
            make.leading.trailing.equalToSuperview().inset(20)
        }
        
        bgView.addSubview(subintro_label)
        subintro_label.snp.makeConstraints { make in
            make.top.equalTo(intro_label.snp.bottom).offset(5)
            make.leading.trailing.equalTo(intro_label)
        }
        
        bgView.addSubview(duration_label)
        duration_label.snp.makeConstraints { make in
            make.top.equalTo(subintro_label.snp.bottom).offset(40)
            make.centerX.equalToSuperview()
        }
        
        bgView.addSubview(operation_stack_view)
        operation_stack_view.snp.makeConstraints { make in
            make.top.equalTo(duration_label.snp.bottom).offset(10)
            make.centerX.equalToSuperview()
        }
    }

    func bindRx() {
        
        dismiss_tap.rx.event
            .filter { $0.state == .ended }
            .asDriver(onErrorJustReturn: dismiss_tap)
            .drive(onNext: { [weak self] _ in
                self?.dismiss(animated: true)
            })
            .disposed(by: disposeBag)
        
        viewModel.state
            .asDriver()
            .distinctUntilChanged()
            .drive(onNext: { [weak self] state in
                self?.re_button.isHidden = state != .check
                self?.save_button.isHidden = state != .check
                self?.record_button.isHidden = state != .ready
                self?.stop_record_button.isHidden = state != .recording
                self?.play_button.isHidden = state != .check
                
                switch state {
                case .recording:
                    self?.recorder_controller.record()
                default:
                    self?.recorder_controller.stop_recording()
                }
            })
            .disposed(by: disposeBag)
        
        Observable.combineLatest(recorder_controller.isPlaying, recorder_controller.isRecording)
            .subscribe(onNext: { [weak self] (isPlaying, isRecording) in
                self?.duration_label.textColor = (isPlaying || isRecording) ? #colorLiteral(red: 0.9960784314, green: 0.7607843137, blue: 0.02745098039, alpha: 1) : #colorLiteral(red: 0.2, green: 0.2, blue: 0.2, alpha: 1)
            })
            .disposed(by: disposeBag)
        
        recorder_controller.recording_time
            .asDriver()
            .map { [weak self] duration in
                "\(self?.date_components_formatter.string(from: duration) ?? "0")s"
            }
            .drive(duration_label.rx.text)
            .disposed(by: disposeBag)
        
        recorder_controller.on_recording_finished
            .asDriver(onErrorJustReturn: ())
            .map { ST_QuickMessageVoiceViewController.State.check }
            .drive(viewModel.state)
            .disposed(by: disposeBag)
        
        recorder_controller.on_playing_finished
            .asDriver(onErrorJustReturn: ())
            .drive(onNext: { [weak self] in
                self?.play_button.imageView.stopAnimating()
            })
            .disposed(by: disposeBag)
        
        record_button.rx.controlEvent(.touchUpInside)
            .asDriver()
            .map { ST_QuickMessageVoiceViewController.State.recording }
            .drive(viewModel.state)
            .disposed(by: disposeBag)
        
        stop_record_button.rx.controlEvent(.touchUpInside)
            .asDriver()
            .map { ST_QuickMessageVoiceViewController.State.check }
            .drive(viewModel.state)
            .disposed(by: disposeBag)
        
        play_button.rx.controlEvent(.touchUpInside)
            .subscribe(onNext: { [weak self] in
                if self?.recorder_controller.player == nil || self?.recorder_controller.player?.isPlaying == false {
                    self?.recorder_controller.play()
                    self?.play_button.imageView.startAnimating()
                } else {
                    self?.recorder_controller.stop_playing()
                    self?.play_button.imageView.stopAnimating()
                }
            })
            .disposed(by: disposeBag)
        
        re_button.rx.controlEvent(.touchUpInside)
            .subscribe(onNext: { [weak self] in
                self?.recorder_controller.stop_playing()
                self?.play_button.imageView.stopAnimating()
                self?.viewModel.state.accept(.ready)
                self?.recorder_controller.recorder?.deleteRecording()
                self?.recorder_controller.recording_time.accept(0)
            })
            .disposed(by: disposeBag)
        
        save_button.rx.controlEvent(.touchUpInside)
            .subscribe(onNext: { [weak self] in
                self?.recorder_controller.stop_playing()
                self?.play_button.imageView.stopAnimating()
                self?.uploadVoice()
            })
            .disposed(by: disposeBag)
    }
    
    func uploadVoice() {
        show_indeterminate_h_u_d()
        viewModel.uploadVoice(url: recorder_controller.url)
            .flatMap(viewModel.add)
            .subscribe(onSuccess: { [weak self] in
                self?.hidden_indeterminate_h_u_d()
                self?.onAdd?()
                self?.dismiss(animated: true)
            }, onFailure: { [weak self] error in
                self?.toast(text: error.localizedDescription)
            })
            .disposed(by: disposeBag)
    }
}

extension ST_QuickMessageVoiceViewController: UIGestureRecognizerDelegate {
    
    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
        // 点击的view为self.view才响应tap手势
        touch.view == view
    }
}
